from datetime import datetime
from flask import request, make_response, json, current_app, jsonify, session
import logging, re, random
from info.models import User
from . import passport_blu
from info import sr, db
from info.until.captcha.captcha import captcha
from info import constants
from info.until.response_code import *
from libs.yuntongxun.sms import *


@passport_blu.route('/image')
def image():
    # 1.获取参数
    # 2.判断是否有参数
    # 3.生成图形验证码
    # 4.将参数存入redis
    # 5.返回图形验证码
    # 如果要获取url？后面的数据则使用args
    imageCodeId = request.args.get('imageCodeId')
    if not imageCodeId:
        return '参数错误'
    name, text, image = captcha.generate_captcha()

    try:
        sr.set('imageCodeId' + imageCodeId, text, constants.IMAGE_CODE_REDIS_EXPIRES)
    except Exception as e:
        logging.debug(e)
    response = make_response(image)
    response.headers['Content-Type'] = 'image/jpg'
    return response


@passport_blu.route('/sms_code', methods=['post'])
def sms_code():
    # 1.获取客户传过来的参数(手机号码，图形验证码，图形验证码的随机值),获取的参数是json格式的字符串
    # 2.判断参数是否为空
    # 3.获取redis的值
    # 4.比较参数和redis的值是否一样
    # 5.生成短信验证码
    # 6.保存短信验证码
    # 7.发送短信验证码
    # 8.通知用户是否发送短信

    data = json.loads(request.data)
    # date= request.json
    mobile = data['mobile']  # 手机号
    image_code = data['image_code']  # 图形验证码
    image_code_id = data['image_code_id']  # 图形验证码的参数
    # 验证参数是否为空
    if not all([mobile, image_code, image_code_id]):
        return jsonify({'errno': RET.PARAMERR, 'errmsg': '参数为空'})
    # 判断手机号是否符合规范
    if not re.match(r'^1[35678][\d]{9}', mobile):
        return jsonify({'errno': RET.USERERR, 'errmsg': '手机号不符合规范'})
    # 从redis获取值
    try:
        result = sr.get('imageCodeId' + image_code_id)
    except Exception as e:
        logging.error(e)
        return jsonify({'errno': RET.DBERR, 'errmsg': '参数不正确'})
    # 过期时间
    if result is None:
        return jsonify({'errno': RET.NODATA, 'errmsg': '验证码过期'})
    # 判断图形验证码是否一样
    if image_code.upper() != result.upper():
        return jsonify({'errno': RET.PARAMERR, 'errmsg': '验证码不一致'})
    # 生成短信验证码
    text_code = '%06d' % random.randint(0, 999999)
    print(text_code)
    # 保存短信验证码到redis
    try:
        sr.setex('Sms' + mobile, constants.SMS_CODE_REDIS_EXPIRES, text_code)
    except Exception as e:
        logging.error(e)
        # current_app.logger.error(e)
        return jsonify({'errno': RET.IOERR, 'errmsg': '保存短信验证码失败'})
    # 发送短信验证码
    text_result = CCP().send_template_sms(mobile, [text_code, (constants.SMS_CODE_REDIS_EXPIRES / 60)], 1)
    # 通知用户发送短信
    if text_result == 0:
        return jsonify({'errno': RET.OK, 'errmsg': '短信发送成功'})
    else:
        return jsonify({'errno': RET.THIRDERR, 'errmsg': '短信发送失败'})


@passport_blu.route('/register', methods=['POST'])
def register():
    """
    1.获取参数  手机号码，短信验证码 密码
    2.判断参数是否为空
    3.取出redis的数据
    4.判断短信验证码是否一致
    5.如果一致，创建用户对象，保存在mysql中
    6.注册成功即默认为登入
    7.返回注册成功
    :return:
    """
    # 获取参数,将json字符串转换为字典
    data = json.loads(request.data)
    mobile = data['mobile']
    smscode = data['smscode']
    password = data['password']
    # 判断参数是否为空
    if not all([mobile, smscode, password]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数为空')
    # 取出数据
    try:
        result = sr.get('Sms' + mobile)
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='短信已过期')
    # 判断短信验证码是否相同
    if result != smscode:
        return jsonify(errno=RET.DATAERR, errmsg='短信验证错误')
    # # 给用户的数据库添加数据
    use = User()
    # 由于用户此刻还没有设置昵称，所以先以手机号为用户名
    use.nick_name = mobile
    # 用户的密码需要加密,将用户加密的数据存入数据库
    use.password = password
    # 用户的手机号
    use.mobile = mobile
    # 用户最后一次的登入事件，默认是注册时间
    use.last_login = datetime.now()
    # 添加数据
    try:
        db.session.add(use)
        db.session.commit()
    except Exception as e:
        logging.error(e)
        db.session.rollback()
        return jsonify(erron=RET.IOERR, errmsg='添加数据失败')
    # 默认为登入
    session['id'] = use.id
    session['nick_name'] = use.nick_name
    session['mobile'] = use.mobile

    return jsonify(erron=RET.OK, errmsg='注册成功')


@passport_blu.route('/login', methods=['post'])
def login():
    """
    1.获取参数  手机号和密码
    2.判断参数是否为空
    3.判断手机是否符合规范
    4.取出数据
    5.判断密码是否一样
    6.设置session,记录登入，保持状态
    7.登入成功
    :return:
    """
    # 获取参数
    data = request.json
    mobile = data.get('mobile')
    password = data.get('password')
    # 判断参数是否为空
    if not all([mobile, password]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数为空')
    # 判断手机是否符合规范
    if not re.match(r'^1[35678][\d]{9}$', mobile):
        return jsonify(errno=RET.USERERR, errmsg='手机号码不符合规范 ')
    # 从数据库获取值
    try:
        result = User.query.filter(mobile == User.mobile).first()
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询数据库失败')
    # 判断是否有该用户
    if not result:
        return jsonify(errno=RET.NODATA, errmsg='没有该用户，请先注册')
    # 判断密码是否一致
    if not result.check_password(password):
        return jsonify(errno=RET.PWDERR, errmsg='密码错误')
    # 设置session
    session['id'] = result.id
    session['mobile'] = mobile
    session['nick_name'] = result.nick_name
    if result.is_admin:
        session['is_admin']=result.is_admin
    # 修改最后一次的登入时间
    try:
        result.last_login= datetime.now()
    except Exception as e:
        logging.error(e)
    # 返回登入成功
    return jsonify(errno=RET.OK, errmsg='登入成功')


@passport_blu.route('/logout')
def logout():
    """
    退出登入只需要将redis保存该用户的数据删除就行了
    :return:
    """
    session.pop('id',None)
    session.pop('nick_name',None)
    session.pop('mobile',None)
    session.pop('is_admin',None)

    return jsonify(errno=RET.OK,errmsg='退出成功')
